/**
  ******************************************************************************
  * @file    py32f420_hal_opa.h
  * @author  MCU Application Team
  * @brief   Header file of OPA HAL module.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 Puya Semiconductor Co.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by Puya under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef PY32F420_HAL_OPA_H
#define PY32F420_HAL_OPA_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "py32f420_hal_def.h"

/** @addtogroup PY32F420_HAL_Driver
  * @{
  */

/** @addtogroup OPA
  * @{
  */

/* Exported types ------------------------------------------------------------*/
/** @defgroup OPA_Exported_Types OPA Exported Types
  * @{
  */

/**
  * @brief  OPA Init structure definition
  */

typedef struct
{
  uint32_t Mode;                        /*!< Specifies the OPA mode
                                             This parameter must be a value of @ref OPA_Mode
                                             mode is either Standalone, Follower or PGA */

  uint32_t InvertingInput;              /*!< Specifies the inverting input in Standalone & Pga modes
                                               - In Standalone mode:   i.e when mode is OPA_STANDALONE_MODE
                                                 This parameter must be a value of @ref OPA_InvertingInput
                                                 InvertingInput is either VINM0 or VINM1
                                               - In PGA mode:          i.e when mode is OPA_PGA_MODE
                                                 & in Follower mode    i.e when mode is OPA_FOLLOWER_MODE
                                                 This parameter is Not Applicable */

  uint32_t NonInvertingInput;           /*!< Specifies the non inverting input of the opa:
                                             This parameter must be a value of @ref OPA_NonInvertingInput
                                             NonInvertingInput is either VINP0, VINP1, VINP2 or VINP3 */

  FunctionalState InternalOutput;       /*!< Specifies the configuration of the internal output from OPA to ADC or COMP.
                                             This parameter can be ENABLE or DISABLE */

  FunctionalState ExternalOutput;       /*!< Specifies the configuration of the external output from OPA to I/O.
                                             This parameter can be ENABLE or DISABLE */

  uint32_t PgaConnect;                  /*!< Specifies the inverting pin in PGA mode
                                             i.e. when mode is OPA_PGA_MODE
                                             This parameter must be a value of @ref OPA_PgaConnect
                                             Either: not connected, connected to VINM0
                                             In this last case, VINM0 can then be used to input signal (negative gain case
                                             with or without bias on VINPx) or to input bias (positive gain case with bias) */

  uint32_t PgaGain;                     /*!< Specifies the gain in PGA mode
                                             i.e. when mode is OPA_PGA_MODE.
                                             This parameter must be a value of @ref OPA_PgaGain
                                             (2, 4, 8, 12，16, 24 or 32) for positive gain & (-1, -3 ,-7, -11，-15, -15 or -31) for negative gain */

  uint32_t CommonModeVoltage;           /*!< Specifies the common-mode voltage
                                            The parameter must be a value of @ref OPA_CommonModeVoltage */

  uint32_t VoltageRefer;                /*!< Specifies the reference voltage
                                            The parameter must be a value of @ref OPA_VoltageRefer */

  uint32_t VoltageBias;                 /*!< Specifies the Voltage bias   
                                            This parameter must be a value of @ref OPA_VoltageBias */
} OPA_InitTypeDef;

/**
  * @brief  HAL State structures definition
  */

typedef enum
{
  HAL_OPA_STATE_RESET               = 0x00000000UL, /*!< OPA is not yet Initialized          */

  HAL_OPA_STATE_READY               = 0x00000001UL, /*!< OPA is initialized and ready for use */
  HAL_OPA_STATE_CALIBBUSY           = 0x00000002UL, /*!< OPA is enabled in auto calibration mode */

  HAL_OPA_STATE_BUSY                = 0x00000004UL, /*!< OPA is enabled and running in normal mode */
  HAL_OPA_STATE_BUSYLOCKED          = 0x00000005UL, /*!< OPA control register is locked
                                                         only system reset allows reconfiguring the opa. */

} HAL_OPA_StateTypeDef;

/**
  * @brief OPA Handle Structure definition
  */
#if (USE_HAL_OPA_REGISTER_CALLBACKS == 1)
typedef struct __OPA_HandleTypeDef
#else
typedef struct
#endif
{
  OPA_TypeDef       *Instance;                    /*!< OPA instance's registers base address   */
  OPA_InitTypeDef   Init;                         /*!< OPA required parameters */
  HAL_StatusTypeDef Status;                         /*!< OPA peripheral status   */
  HAL_LockTypeDef   Lock;                           /*!< Locking object          */
  __IO HAL_OPA_StateTypeDef  State;               /*!< OPA communication state */

#if (USE_HAL_OPA_REGISTER_CALLBACKS == 1)
  void (* MspInitCallback)(struct __OPA_HandleTypeDef *hopa);
  void (* MspDeInitCallback)(struct __OPA_HandleTypeDef *hopa);
#endif /* USE_HAL_OPA_REGISTER_CALLBACKS */

} OPA_HandleTypeDef;

#if (USE_HAL_OPA_REGISTER_CALLBACKS == 1)
/**
  * @brief  HAL OPA Callback ID enumeration definition
  */
typedef enum
{
  HAL_OPA_MSPINIT_CB_ID                     = 0x01UL,  /*!< OPA MspInit Callback ID           */
  HAL_OPA_MSPDEINIT_CB_ID                   = 0x02UL,  /*!< OPA MspDeInit Callback ID         */
  HAL_OPA_ALL_CB_ID                          = 0x03UL   /*!< OPA All ID                        */
} HAL_OPA_CallbackIDTypeDef;

/**
  * @brief  HAL OPA Callback pointer definition
  */
typedef void (*pOPA_CallbackTypeDef)(OPA_HandleTypeDef *hopa);
#endif /* USE_HAL_OPA_REGISTER_CALLBACKS */
/**
  * @}
  */

/* Exported constants --------------------------------------------------------*/
/** @defgroup OPA_Exported_Constants OPA Exported Constants
  * @{
  */
/** @defgroup OPA_Mode OPA Mode
  * @{
  */
#define OPA_STANDALONE_MODE            (0x00000000UL)        /*!< standalone mode */
#define OPA_PGA_MODE                   OPA_CSR_MODE_0      /*!< PGA mode */
#define OPA_FOLLOWER_MODE              OPA_CSR_MODE_1        /*!< follower mode */
/**
  * @}
  */

/** @defgroup OPA_NonInvertingInput OPA Non Inverting Input
  * @{
  */
#define OPA_NONINVERTINGINPUT_IO0         (0x00000000UL)        /*!< Non inverting input connected to I/O VINP0
                                                                       (PC2  for OPA1, PA1  for OPA2, PA5  for OPA3, Fixed PB0 for OPA4) */

#define OPA_NONINVERTINGINPUT_IO1         OPA_CSR_VPSEL     /*!< Non inverting input connected to I/O VINP1
                                                                       (PC0  for OPA1, PA3 for OPA2, PD5 for OPA3, Fixed PB0 for OPA4) */
/**
  * @}
  */

/** @defgroup OPA_InvertingInput OPA Inverting Input
  * @{
  */
#define OPA_INVERTINGINPUT_IO0       (0x00000000UL)                                /*!< Inverting input connected to I/O VINM0
                                                                                    (PC3 for OPA1, PA2 for OPA2, PA6 for OPA3, PB1 for OPA4) */
                                                                    
#define OPA_INVERTINGINPUT_IO1       (                  OPA_CSR_VNSEL_0)           /*!< Inverting input connected to I/0 VINM1 or OPA1_VINN1
                                                                                    (PC1 for OPA1, PD4 for OPA2, PA4 for OPA3, OPA1_VINN1 for OPA4) */
                                                                                    
#define OPA_INVERTINGINPUT_IO2      (OPA_CSR_VNSEL_1                   )           /*!< Inverting input connected to OPA1_VINN1
                                                                                    (None for OPA1, OPA1_VINN1 for OPA2, OPA1_VINN1 for OPA3,None for OPA4) */
/**
  * @}
  */

/** @defgroup OPA_CommonModeVoltage OPA Common-Mode Voltage
  * @{
  */
#define OPA_COMMONMODEVOLTAGE_EXTERNAL        (0x00000000UL)        /*!< The common mode voltage is set to be the external voltage */
#define OPA_COMMONMODEVOLTAGE_BUILDIN         (OPA_CSR_VBSEL)   /*!< The common mode voltage is set to be the built-in voltage */
/**
  * @}
  */

/** @defgroup OPA_VoltageRefer OPA Reference Voltage
  * @{
  */
#define OPA_VOLTAGEREFER_VCC        (0x00000000UL)        /*!< The reference voltage is set to be the VCC */
#define OPA_VOLTAGEREFER_VREFBUF    (OPA_CSR_VREF_SEL)   /*!< The reference voltage is set to be the VREFBUF */
/**
  * @}
  */

/** @defgroup OPA_VoltageBias OPA Voltage Bias
  * @{
  */
#define OPA_VOLTAGEBIAS_DIV1       (0x00000000UL)                                                              /*!< The bias voltage is set to be the div1 of VCC/VREFBUF */            
#define OPA_VOLTAGEBIAS_DIV2       (                                                         OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div2 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV3       (                                      OPA_CSR_VBIAS_1                   ) /*!< The bias voltage is set to be the div3 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV4       (                                      OPA_CSR_VBIAS_1 | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div4 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV5       (                   OPA_CSR_VBIAS_2                                      ) /*!< The bias voltage is set to be the div5 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV6       (                   OPA_CSR_VBIAS_2                    | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div6 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV7       (                   OPA_CSR_VBIAS_2 | OPA_CSR_VBIAS_1                   ) /*!< The bias voltage is set to be the div7 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV8       (                   OPA_CSR_VBIAS_2 | OPA_CSR_VBIAS_1 | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div8 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV9       (OPA_CSR_VBIAS_3                                                         ) /*!< The bias voltage is set to be the div9 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV10      (OPA_CSR_VBIAS_3                                       | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div10 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV11      (OPA_CSR_VBIAS_3                    | OPA_CSR_VBIAS_1                   ) /*!< The bias voltage is set to be the div11 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV12      (OPA_CSR_VBIAS_3                    | OPA_CSR_VBIAS_1 | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div12 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV13      (OPA_CSR_VBIAS_3 | OPA_CSR_VBIAS_2                                      ) /*!< The bias voltage is set to be the div13 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV14      (OPA_CSR_VBIAS_3 | OPA_CSR_VBIAS_2                    | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div14 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV15      (OPA_CSR_VBIAS_3 | OPA_CSR_VBIAS_2 | OPA_CSR_VBIAS_1                   ) /*!< The bias voltage is set to be the div15 of VCC/VREFBUF */
#define OPA_VOLTAGEBIAS_DIV16      (OPA_CSR_VBIAS_3 | OPA_CSR_VBIAS_2 | OPA_CSR_VBIAS_1 | OPA_CSR_VBIAS_0) /*!< The bias voltage is set to be the div16 of VCC/VREFBUF */
/**
  * @}
  */

/** @defgroup OPA_PgaConnect OPA Pga Connect
  * @{
  */
#define OPA_PGA_CONNECT_INVERTINGINPUT_NO               (0x00000000UL)                            /*!< In PGA mode, the inverting input is not connected */
#define OPA_PGA_CONNECT_INVERTINGINPUT_IO0_BIAS         OPA_CSR_PGA_GAIN_3                        /*!< In PGA mode, the inverting input is connected to VINM0
                                                                                                      - Input signal on VINM0, bias on VINPx: negative gain
                                                                                                      - Bias on VINM0, input signal on VINPx: positive gain */
/**
  * @}
  */

/** @defgroup OPA_PgaGain OPA Pga Gain
  * @note Gain sign:
  *         - is positive if the @ref OPA_PgaConnect configuration is
  *           @ref OPA_PGA_CONNECT_INVERTINGINPUT_NO
  *         - may be positive or negative if the @ref OPA_PgaConnect configuration is
  *           @ref OPA_PGA_CONNECT_INVERTINGINPUT_IO0_BIAS
  *       see @ref OPA_PgaConnect for more details
  * @{
  */
#define OPA_PGA_GAIN_2_OR_MINUS_1          (0x00000000UL)                                                      /*!< PGA gain could be 2  or -1  */
#define OPA_PGA_GAIN_4_OR_MINUS_3          (                                          OPA_CSR_PGA_GAIN_0)      /*!< PGA gain could be 4  or -3  */
#define OPA_PGA_GAIN_8_OR_MINUS_7          (                     OPA_CSR_PGA_GAIN_1                     )      /*!< PGA gain could be 8  or -7  */
#define OPA_PGA_GAIN_12_OR_MINUS_11        (                     OPA_CSR_PGA_GAIN_1 | OPA_CSR_PGA_GAIN_0)      /*!< PGA gain could be 12 or -11 */
#define OPA_PGA_GAIN_16_OR_MINUS_15        (OPA_CSR_PGA_GAIN_2                                          )      /*!< PGA gain could be 16 or -15 */
#define OPA_PGA_GAIN_24_OR_MINUS_23        (OPA_CSR_PGA_GAIN_2                      | OPA_CSR_PGA_GAIN_0)      /*!< PGA gain could be 24 or -23 */
#define OPA_PGA_GAIN_32_OR_MINUS_31        (OPA_CSR_PGA_GAIN_2 | OPA_CSR_PGA_GAIN_1                     )      /*!< PGA gain could be 32 or -31 */
/**
  * @}
  */

/**
  * @}
  */



/* Private constants ---------------------------------------------------------*/
/** @defgroup OPA_Private_Constants OPA Private Constants
  * @brief   OPA Private constants and defines
  * @{
  */
/** @defgroup OPA_Input OPA Input
  * @{
  */
#define OPA_INPUT_INVERTING                 (24UL) /*!< Inverting input */
#define OPA_INPUT_NONINVERTING              (19UL) /*!< Non inverting input */

#define IS_OPA_INPUT(INPUT) (((INPUT) == OPA_INPUT_INVERTING) || \
                               ((INPUT) == OPA_INPUT_NONINVERTING))
/**
  * @}
  */

/**
  * @}
  */


/* Private macro -------------------------------------------------------------*/

/** @defgroup OPA_Private_Macros OPA Private Macros
  * @{
  */

#if defined(OPA_FOLLOWER_MODE)
#define IS_OPA_FUNCTIONAL_NORMALMODE(INPUT) (((INPUT) == OPA_STANDALONE_MODE) || \
                                               ((INPUT) == OPA_PGA_MODE) || \
                                               ((INPUT) == OPA_FOLLOWER_MODE))
#else
#define IS_OPA_FUNCTIONAL_NORMALMODE(INPUT) (((INPUT) == OPA_STANDALONE_MODE) || \
                                               ((INPUT) == OPA_PGA_MODE))
#endif

#define IS_OPA_NONINVERTING_INPUT(INPUT) (((INPUT) == OPA_NONINVERTINGINPUT_IO0) || \
                                            ((INPUT) == OPA_NONINVERTINGINPUT_IO1))

#define IS_OPA_INVERTING_INPUT(INPUT) (((INPUT) == OPA_INVERTINGINPUT_IO0) || \
                                         ((INPUT) == OPA_INVERTINGINPUT_IO1) || \
                                         ((INPUT) == OPA_INVERTINGINPUT_IO2))

#define IS_OPA_PGACONNECT(CONNECT) (((CONNECT) == OPA_PGA_CONNECT_INVERTINGINPUT_NO)            || \
                                      ((CONNECT) == OPA_PGA_CONNECT_INVERTINGINPUT_IO0_BIAS))

#define IS_OPA_PGA_GAIN(GAIN) (((GAIN) == OPA_PGA_GAIN_2_OR_MINUS_1)   || \
                                 ((GAIN) == OPA_PGA_GAIN_4_OR_MINUS_3)   || \
                                 ((GAIN) == OPA_PGA_GAIN_8_OR_MINUS_7)   || \
                                 ((GAIN) == OPA_PGA_GAIN_12_OR_MINUS_11) || \
                                 ((GAIN) == OPA_PGA_GAIN_16_OR_MINUS_15) || \
                                 ((GAIN) == OPA_PGA_GAIN_24_OR_MINUS_23) || \
                                 ((GAIN) == OPA_PGA_GAIN_32_OR_MINUS_31))

#define IS_OPA_COMMONMODE_VOLTAGE(VOLTAGE) (((VOLTAGE) == OPA_COMMONMODEVOLTAGE_EXTERNAL) || \
                                            ((VOLTAGE) == OPA_COMMONMODEVOLTAGE_BUILDIN))

#define IS_OPA_VOLTAGEREFER(VOLTAGE) (((VOLTAGE) == OPA_VOLTAGEREFER_VCC) || \
                                      ((VOLTAGE) == OPA_VOLTAGEREFER_VREFBUF))
                                      
#define IS_OPA_VOLTAGEBIAS(BIAS) (((BIAS) == OPA_VOLTAGEBIAS_DIV1)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV2)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV3)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV4)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV5)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV6)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV7)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV8)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV9)   || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV10)  || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV11)  || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV12)  || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV13)  || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV14)  || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV15)  || \
                                  ((BIAS) == OPA_VOLTAGEBIAS_DIV16))                                      
/**
  * @}
  */


/* Exported macros -----------------------------------------------------------*/
/** @defgroup OPA_Exported_Macros OPA Exported Macros
  * @{
  */

/** @brief Reset OPA handle state
  * @param  __HANDLE__ OPA handle.
  * @retval None
  */
#define __HAL_OPA_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_OPA_STATE_RESET)

/**
  * @}
  */

/* Exported functions --------------------------------------------------------*/
/** @defgroup OPA_Exported_Functions OPA Exported Functions
  * @{
  */

/** @defgroup OPA_Exported_Functions_Group1 Initialization and de-initialization functions
  * @{
  */

/* Initialization/de-initialization functions  **********************************/
HAL_StatusTypeDef HAL_OPA_Init(OPA_HandleTypeDef *hopa);
HAL_StatusTypeDef HAL_OPA_DeInit(OPA_HandleTypeDef *hopa);
void HAL_OPA_MspInit(OPA_HandleTypeDef *hopa);
void HAL_OPA_MspDeInit(OPA_HandleTypeDef *hopa);
/**
  * @}
  */


/** @defgroup OPA_Exported_Functions_Group2 Input and Output operation functions
  * @{
  */

/* I/O operation functions  *****************************************************/
HAL_StatusTypeDef HAL_OPA_Start(OPA_HandleTypeDef *hopa);
HAL_StatusTypeDef HAL_OPA_Stop(OPA_HandleTypeDef *hopa);


/**
  * @}
  */

/** @defgroup OPA_Exported_Functions_Group3 Peripheral Control functions
  * @{
  */

/* Peripheral Control functions  ************************************************/
#if (USE_HAL_OPA_REGISTER_CALLBACKS == 1)
/* OPA callback registering/unregistering */
HAL_StatusTypeDef HAL_OPA_RegisterCallback(OPA_HandleTypeDef *hopa, HAL_OPA_CallbackIDTypeDef CallbackId,
                                             pOPA_CallbackTypeDef pCallback);
HAL_StatusTypeDef HAL_OPA_UnRegisterCallback(OPA_HandleTypeDef *hopa, HAL_OPA_CallbackIDTypeDef CallbackId);
#endif /* USE_HAL_OPA_REGISTER_CALLBACKS */

HAL_StatusTypeDef HAL_OPA_Lock(OPA_HandleTypeDef *hopa);

/**
  * @}
  */

/** @defgroup OPA_Exported_Functions_Group4 Peripheral State functions
  * @{
  */

/* Peripheral State functions  **************************************************/
HAL_OPA_StateTypeDef HAL_OPA_GetState(OPA_HandleTypeDef *hopa);

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */


#ifdef __cplusplus
}
#endif

#endif /* PY32F420_HAL_OPA_H */

